#pragma once
#include <iostream>
#include <string>

#include <cstring>

namespace dsh_protocol
{
    #define MYSELF 1
    #define SPACE " "
    #define SPACE_LEN strlen(SPACE)

    class Request
    {
    public:
        std::string Serialize() // 序列化 -> "x_ op_ y_"
        {
            // 自己实现
            // 现成的方案
        #ifdef MYSELF
            std::string str;
            str = std::to_string(x_);
            str += SPACE;
            str += op_;
            str += SPACE;
            str += std::to_string(y_);
            return str;
        #else
        #endif 
        }

        bool Deserialize(const std::string& str) // 反序列化 "x_ op_ y_" -> 结构化数据
        {
        #ifdef MYSELF
            std::size_t left = str.find(SPACE);
            if (left == std::string::npos) return false;
            std::size_t right = str.rfind(SPACE);
            x_ = stoi(str.substr(0, left));
            y_ = stoi(str.substr(right + SPACE_LEN));
            op_ = str[left + SPACE_LEN];
            return true;
        #else
        #endif 
        }

    public:
        Request(){}
        Request(int x, int y, char op)
            :x_(x)
            ,y_(y)
            ,op_(op)
        {}
        ~Request(){}
    public:
        int x_;
        int y_;
        char op_;
    };

    class Response
    {
    public:
        std::string Serialize() // 序列化 -> "code_ result_"
        {
        #ifdef MYSELF
            std::string s;
            s = std::to_string(code_);
            s += SPACE;
            s += std::to_string(result_);
            return s;
        #else
        #endif  
        }

        bool Deserialize(const std::string& str) // 反序列化 "code_ result_" -> 结构化数据
        {
        #ifdef MYSELF
            std::size_t pos = str.find(SPACE);
            if (pos == std::string::npos) return false;
            code_ = stoi(str.substr(0, pos));
            result_ = stoi(str.substr(pos + SPACE_LEN));
            return true;
        #else
        #endif  
        }
    public:
        Response(){}
        Response(int result, int code)
            :result_(result)
            ,code_(code)
        {}
        ~Response(){}
    public:
        int result_; // 结果
        int code_;   // 结果状态码
    };

    bool Recv(int sock, std::string* out)
    {
        char buffer[1024];
        ssize_t s = recv(sock, buffer, sizeof(buffer) - 1, 0);
        if (s > 0)
        {
            buffer[s] = 0;
            *out += buffer;
        }
        else if (s == 0)
        {
            std::cout << "client quit" << std::endl;
            return false;
        }
        else
        {
            std::cout << "recv error" << std::endl;
            return false;
        }
        return true;
    }
    void Send(int sock, const std::string str)
    {
        send(sock, str.c_str(), str.size(), 0);
    }
    
#define SEP "\r\n"
#define SEP_LEN strlen(SEP)
    // len\r\nx_ op_ y_\r\n
    std::string Decode(std::string &buffer)
    {
        std::size_t pos = buffer.find(SEP);
        if (pos == std::string::npos) return "";
        int size = atoi(buffer.substr(0, pos).c_str()); // 拿到len
        int surplus = buffer.size() - pos - 2 * SEP_LEN; // 去掉len和两个标记符的长度
        if (surplus >= size)
        {
            // 至少有一个完整的报文
            buffer.erase(0, pos + SEP_LEN); // 去掉len\r\n
            std::string s = buffer.substr(0, size); // 提取x_ op_ y_
            buffer.erase(0, size + SEP_LEN); // 去掉x_ op_ y_\r\n
            return s;
            // 后面就是新的报文了  
        }
        else return "";
    }

    // len\r\nXXXXXXX\r\n
    std::string Encode(std::string& s)
    {
        std::string len = std::to_string(s.size());
        std::string new_package = len;
        new_package += SEP;
        new_package += s;
        new_package += SEP;
        return new_package;
    }
}